<script setup lang="ts">
    import { ref, reactive, onMounted, watch, computed, inject } from 'vue';
    import { typeEnum } from '@/enums';
    import { api } from "@/services/api";
    import { setToken } from '@/utils/auth';
    import { Message, Lock } from '@element-plus/icons-vue';
    import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
    import { userLoginStore, LoginStatus } from '@/stores/login';
    import { useJsencryptStore } from '@/stores/jsencrypt';
    import { useUserStore } from '@/stores/user';
    import { WsRequestMsgType } from '@/utils/wsType';
    import { UserInfo } from '@/services/type';

    import loadingSvg from "@/assets/icons/loading-empty.svg";
    import wsIns from '@/utils/websocket';

    // 属性
    defineProps<{visible: boolean}>();

    const loginStore = userLoginStore();
    const jsencryptStore = useJsencryptStore();
    const userStore = useUserStore();
    const loginFormRef = ref<FormInstance>();
    const msg: any = inject('message');

    // 登录信息
    const loginForm = reactive({
        // 邮箱
        email: '',
        // 密码
        passWord: '',
        // 验证码
        code: ''
    });
    // 验证码参数
    const captchaOption = ref({
        // 验证码
        code: "",
        // 验证码是否加载中
        loading: true,
        // 验证码地址
        imgUrl: ""
    });

    // 是否打开登录框
    const isShowLoginBox = computed(() => loginStore.isShowLoginBox);

    // 监听，初始化不执行
    watch(isShowLoginBox, (data) => {
        if(data) {
            // 获取验证码
            getCode();
        }
    });

    const validateCode = (rule: any, value: any, callback: any) => {
        if (value === '') {
            callback(new Error('验证码不能为空'));
        } else {
            if (loginForm.code !== captchaOption.value.code) {
                callback(new Error('请输入正确的验证码'))
            }
            callback()
        }
    }

    // 校验规则
    const rules = reactive<FormRules>({
        email: [
            { required: true, message: '邮箱不能为空', trigger: 'blur' },
            { required: true, pattern: /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/, message: '邮箱格式错误', trigger: 'blur' }
        ],
        passWord: [
            { required: true, message: '密码不能为空', trigger: 'blur' },
            { required: true, pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$/, message: '密码必须包含字母和数字，且在6~18位之间', trigger: 'blur' }
        ],
        code: [
            { validator: validateCode, trigger: 'blur' }
        ]
    });

    /**
     * 获取验证码
     */
    const getCode: any = async () => {
        // 获取验证码
        const response = await api.common.getCodeImg();
        if(response.code != 0) {
            return msg.info("获取验证码失败！");
        }
        // 验证码
        captchaOption.value.code = response.data.code;
        // 验证码图片
        captchaOption.value.imgUrl = "data:image/gif;base64," + response.data.img;
        // 验证码结束加载
        captchaOption.value.loading = false;
    }

    // 登录事件
    const login = async (formEl: FormInstance | undefined) => {
        if (!formEl) return;
        await formEl.validate(async (valid) => {
            if (valid) {
                // 等待登录
                loginStore.loginStatus = LoginStatus.Waiting;
                // 密码加密
                const { key, value } = await jsencryptStore.encryptData(loginForm.passWord);
                // 登录
                const response = await api.common.login({
                    username: loginForm.email,
                    password: value,
                    key,
                    code: loginForm.code
                });
                if(response.code === 0) {
                    // 获取登录用户信息
                    const data = await userStore.getInfo() as UserInfo;
                    // 发送信息到后台，提醒用户登录成功
                    wsIns.send({ type: WsRequestMsgType.LOGIN_SUCCESS, data });
                    // 设置token
                    setToken(response.data.token);
                    // token赋值
                    loginStore.token = response.data.token;
                    // 登录成功
                    loginStore.loginStatus = LoginStatus.Success;
                    // 关闭登录弹窗
                    loginStore.isShowLoginBox = false;
                    // 清空字段值
                    formEl.resetFields();
                } else {
                    // 重新获取验证码
                    getCode();
                    // 初始化登录状态
                    loginStore.loginStatus = LoginStatus.Init;
                    // 错误提示
                    ElMessage.error(response.msg);
                }
            } else {
                // 重新获取验证码
                getCode();
            }
        })
    }

    onMounted(() => {
        // 初始化，获取验证码
        getCode();
    });

</script>

<template>
    <div class="login-wrap-box" v-show="visible">
        <el-form :model="loginForm" :rules="rules" ref="loginFormRef" class="from-box">
            <div class="email">
                <el-form-item prop="email">
                    <el-input size="large" placeholder="请输入电子邮箱" :prefix-icon="Message" v-model="loginForm.email" autocomplete="off"></el-input>
                </el-form-item>
            </div>
            <div class="passWord">
                <el-form-item prop="passWord">
                    <el-input size="large" placeholder="请输入密码" :prefix-icon="Lock" v-model="loginForm.passWord" show-password autocomplete="off"></el-input>
                </el-form-item>
            </div>
            <div class="verCode">
                <div class="container">
                    <el-form-item prop="code">
                        <el-input
                            placeholder="请输入验证码"
                            v-model="loginForm.code"
                            size="large"
                        >
                            <template #prefix>
                                <svg-icon href="#icon-code" width="14px" height="14px" fill="#a8abb2"></svg-icon>
                            </template>
                        </el-input>
                    </el-form-item>
                    <div class="image">
                        <img v-if="captchaOption.loading" class="code-loading" :src="loadingSvg" />
                        <img v-if="!captchaOption.loading" class="login-code-img" :src="captchaOption.imgUrl" @click="getCode" />
                    </div>
                </div>
            </div>
            <div class="btn-box">
                <el-button type="primary" size="large" style="width: 100%" @click="login(loginFormRef)" :loading="loginStore.loginStatus === LoginStatus.Waiting">登  录</el-button>
                <div class="info clearfix">
                    <p class="info-item fl">没有账号？<span class="registerBtn" @click="$emit('switch', typeEnum.REGISTER)">注册</span></p>
                    <!-- <p class="forgotPasBtn fr" style="line-height: 30px">忘记密码？</p> -->
                </div>
            </div>
        </el-form>
    </div>
</template>
<!-- 引入样式文件 -->
<style lang="less" src="./style.less" scoped />